/*****************************************************************************
 *
 * neb2ipc.C - NEB Module to export data to a message queue
 *
 * Copyright (c) 2009 Intelie
 *
 *
 *****************************************************************************/

/* include (minimum required) event broker header files */
#include "./include/nebmodules.h"
#include "./include/nebcallbacks.h"

/* include other event broker header files that we need for our work */
#include "./include/nebstructs.h"
#include "./include/broker.h"

/* include some Nagios stuff as well */
#include "./include/config.h"
#include "./include/common.h"
#include "./include/nagios.h"

/* includes for IPC */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include <string.h>


/* specify event broker API version (required) */
NEB_API_VERSION(CURRENT_NEB_API_VERSION);

/* variables for ipc */
#define KEY 123456
int msqid;
struct my_msgbuf {
    long mtype;
    char mtext[512];
} buf;

void *neb2ipc_module_handle=NULL;

void neb2ipc_reminder_message(char *);
int neb2ipc_handle_data(int,void *);


/* this function gets called when the module is loaded by the event broker */
int nebmodule_init(int flags, char *args, nebmodule *handle){
	char temp_buffer[1024];
	time_t current_time;
	unsigned long interval;

	/* save our handle */
	neb2ipc_module_handle=handle;

	/* set some info - this is completely optional, as Nagios doesn't do anything with this data */
	neb_set_module_info(neb2ipc_module_handle,NEBMODULE_MODINFO_TITLE,"neb2ipc");
	neb_set_module_info(neb2ipc_module_handle,NEBMODULE_MODINFO_AUTHOR,"Intelie");
	neb_set_module_info(neb2ipc_module_handle,NEBMODULE_MODINFO_TITLE,"neb2ipc");
	neb_set_module_info(neb2ipc_module_handle,NEBMODULE_MODINFO_VERSION,"noversion");
	neb_set_module_info(neb2ipc_module_handle,NEBMODULE_MODINFO_LICENSE,"GPL v3");
	neb_set_module_info(neb2ipc_module_handle,NEBMODULE_MODINFO_DESC,"A Nagios Event Broker (NEB) module to integrate with activemq.");

	/* log module info to the Nagios log file */
	write_to_all_logs("neb2ipc: Copyright (c) 2009 Intelie",NSLOG_INFO_MESSAGE);

	/* log a message to the Nagios log file */
	temp_buffer[sizeof(temp_buffer)-1]='\x0';
	write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);

	/* log a reminder message every 15 minutes (how's that for annoying? :-)) */
	time(&current_time);
	interval=900;
	schedule_new_event(EVENT_USER_FUNCTION,TRUE,current_time+interval,TRUE,interval,NULL,TRUE,(void *)neb2ipc_reminder_message,"Processing events to activemq",0);

	/* register to be notified of check events */
	neb_register_callback(NEBCALLBACK_HOST_CHECK_DATA,neb2ipc_module_handle,0,neb2ipc_handle_data);
	neb_register_callback(NEBCALLBACK_SERVICE_CHECK_DATA,neb2ipc_module_handle,0,neb2ipc_handle_data);

	/* create a message queue */
	/* the path and id are used just to create a unique key */
/*    if ((key = ftok("/usr/local/nagios/var", 1)) == -1){
    	snprintf(temp_buffer,sizeof(temp_buffer)-1,"neb2ipc: System was unable to generate key for message queue.");
    	temp_buffer[sizeof(temp_buffer)-1]='\x0';
    	write_to_all_logs(temp_buffer, NSLOG_RUNTIME_ERROR);
    	return 1;
    }*/

    if ( (msqid = msgget(KEY, IPC_CREAT | 0600)) == -1){
    	snprintf(temp_buffer,sizeof(temp_buffer)-1,"neb2ipc: System was unable to create message queue.");
    	temp_buffer[sizeof(temp_buffer)-1]='\x0';
    	write_to_all_logs(temp_buffer, NSLOG_RUNTIME_ERROR);
    	return 1;
    }

    snprintf(temp_buffer,sizeof(temp_buffer)-1,"neb2ipc: Created message queue %i.",msqid);
    temp_buffer[sizeof(temp_buffer)-1]='\x0';
    write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);


	return 0;
        }


/* this function gets called when the module is unloaded by the event broker */
int nebmodule_deinit(int flags, int reason){
	char temp_buffer[1024];

	/* deregister for all events we previously registered for... */
	neb_deregister_callback(NEBCALLBACK_HOST_CHECK_DATA,neb2ipc_handle_data);
	neb_deregister_callback(NEBCALLBACK_SERVICE_CHECK_DATA,neb2ipc_handle_data);

	/* log a message to the Nagios log file */
	snprintf(temp_buffer,sizeof(temp_buffer)-1,"neb2ipc: Goodbye!\n");
	temp_buffer[sizeof(temp_buffer)-1]='\x0';
	write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);


//	if (msgctl(msqid, IPC_RMID, NULL) == -1) {
//		/* log a message to the Nagios log file */
//			snprintf(temp_buffer,sizeof(temp_buffer)-1,"Could remove message queue id %i: %s",msqid, strerror(errno));
//			temp_buffer[sizeof(temp_buffer)-1]='\x0';
//			write_to_all_logs(temp_buffer,NSLOG_RUNTIME_ERROR);
//	}

	return 0;
        }


/* gets called every X minutes by an event in the scheduling queue */
void neb2ipc_reminder_message(char *message){
	char temp_buffer[1024];

	/* log a message to the Nagios log file */
	snprintf(temp_buffer,sizeof(temp_buffer)-1,"neb2ipc: I'm still here! %s", message);
	temp_buffer[sizeof(temp_buffer)-1]='\x0';
	write_to_all_logs(temp_buffer,NSLOG_INFO_MESSAGE);

	return;
        }


/* handle data from Nagios daemon */
int neb2ipc_handle_data(int event_type, void *data){

	nebstruct_host_check_data *hcdata=NULL;
	nebstruct_service_check_data *scdata=NULL;

	char temp_buffer[1024];

	buf.mtype = event_type;

	/* what type of event/data do we have? */
	switch(event_type){

	case NEBCALLBACK_HOST_CHECK_DATA:

		if((hcdata=(nebstruct_host_check_data *)data)){

      if (hcdata->type != NEBTYPE_HOSTCHECK_PROCESSED) {
          // Check not processed yet
          return 0;
      }
			
      if (hcdata->host_name == NULL || strlen(hcdata->host_name) == 0 || 
          hcdata->output == NULL || strlen(hcdata->output) == 0) {
          
          snprintf(temp_buffer, sizeof(temp_buffer)-1, "Host check error: Missing one or more parameters:\n  host_name: %s\n  output: %s", hcdata->host_name, hcdata->output);
          temp_buffer[sizeof(temp_buffer)-1]='\x0';
          write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);

          return 0;
      }

			/* send message to message queue */
			snprintf(buf.mtext,sizeof(buf.mtext)-1,"%s^%s\0", hcdata->host_name, hcdata->output);
			
			if (msgsnd(msqid, (struct buf *)&buf, sizeof(buf), IPC_NOWAIT) == -1){
				snprintf(temp_buffer,sizeof(temp_buffer)-1,"Error to send message to queue id %i: %s", msqid, strerror(errno));
				temp_buffer[sizeof(temp_buffer)-1]='\x0';
				write_to_all_logs(temp_buffer,NSLOG_RUNTIME_WARNING);
			 }
		}
		break;

	case NEBCALLBACK_SERVICE_CHECK_DATA:

		if((scdata=(nebstruct_service_check_data *)data)){
			
			if (scdata->type != NEBTYPE_SERVICECHECK_PROCESSED) {
          // Check not processed yet
          return 0;
      }
			
			// If command_name comes null, search on service struct
			char *command_name;
			if (scdata->command_name != NULL && strlen(scdata->command_name) > 0) {
				command_name = scdata->command_name;
			} else {
				service *svc;
				
				if ((svc = find_service(scdata->host_name, scdata->service_description)) == NULL) {
					snprintf(temp_buffer, sizeof(temp_buffer)-1, "Could not find service %s for host %s", scdata->service_description, scdata->host_name);
	        temp_buffer[sizeof(temp_buffer)-1]='\x0';
	        write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);
					return 0;
				}
				if (svc->service_check_command != NULL) {
					command_name = strtok(svc->service_check_command, "!");
					if (command_name == NULL) {
						command_name = svc->service_check_command;
					}
				}
			}
		
      if (scdata->host_name == NULL || strlen(scdata->host_name) == 0 || 
          command_name == NULL || strlen(command_name) == 0 ||
          scdata->output == NULL || strlen(scdata->output) == 0) {
          
          snprintf(temp_buffer, sizeof(temp_buffer)-1, "Service check error: Missing one or more parameters:\n  host_name: %s\n  command_name: %s\n  output: %s", 
                                  scdata->host_name, command_name, scdata->output);
          temp_buffer[sizeof(temp_buffer)-1]='\x0';
          write_to_all_logs(temp_buffer, NSLOG_INFO_MESSAGE);

          return 0;
      }
      
			snprintf(buf.mtext,sizeof(buf.mtext)-1,"%s^%s^%i^%s\0",scdata->host_name,command_name,scdata->state,scdata->output);
			
			if (msgsnd(msqid, (struct buf *)&buf, sizeof(buf), IPC_NOWAIT) == -1){
				snprintf(temp_buffer,sizeof(temp_buffer)-1," Error to send message to queue id %i: %s", msqid, strerror(errno));
				temp_buffer[sizeof(temp_buffer)-1]='\x0';
				write_to_all_logs(temp_buffer,NSLOG_RUNTIME_WARNING);
			}
		}

		break;

	default:
		break;
	        }

	return 0;
        }


